using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

using BlogEngine.Core.Providers;

namespace BlogEngine.Core
{
	/// <summary>
	/// A page is much like a post, but is not part of the
	/// blog chronology and is more static in nature.
	/// <remarks>
	/// Pages can be used for "About" pages or other static
	/// information.
	/// </remarks>
	/// </summary>
	[Serializable, DataObject]
	public class Page : Postable<Page>
	{
		#region Constructor

		/// <summary>
		/// The contructor sets default values.
		/// </summary>
		public Page()
		{
			DateCreated = DateTime.Now;
		}

		#endregion

		#region Properties

		private bool _IsFrontPage;
		/// <summary>
		/// Gets or sets whether or not this page should be displayed on the front page.
		/// </summary>
		public bool IsFrontPage
		{
			get { return _IsFrontPage; }
			set
			{
				if (_IsFrontPage != value) OnPropertyChanged("IsFrontPage");
				_IsFrontPage = value;
			}
		}

		/// <summary>
		/// The relative URI to the page. For in-site use only.
		/// </summary>
		public Uri PermaLink
		{
			get { return new Uri(Utils.RelativeWebRoot + "page/" + Utils.RemoveIllegalCharacters(Title) + BlogSettings.Instance.FileExtension, UriKind.Relative); }
		}

		private static object _SyncRoot = new object();
		private static List<Page> _Pages;
		/// <summary>
		/// Gets an unsorted list of all pages.
		/// </summary>
		public static List<Page> Pages
		{
			get
			{
				if (_Pages == null)
				{
					lock (_SyncRoot)
					{
						if (_Pages == null)
							_Pages = BlogService.SelectPages();
					}
				}

				return _Pages;
			}
		}

		/// <summary>
		/// Returns a page based on the specified id.
		/// </summary>
		public static Page GetPage(int id)
		{
			return BlogService.SelectPage(id);
		}

		/// <summary>
		/// Returns the front page if any is available.
		/// </summary>
		public static Page GetFrontPage()
		{
			foreach (Page page in Pages)
			{
				if (page.IsFrontPage)
					return page;
			}

			return null;
		}

		#endregion

		#region Base overrides

		/// <summary>
		/// Validates the properties on the Page.
		/// </summary>
		protected override void Validate()
		{
			AddError(String.IsNullOrEmpty(Title), "Title", "Title must be set");
			AddError(String.IsNullOrEmpty(Content), "Content", "Content must be set");
		}

		/// <summary>
		/// Retrieves a page form the BlogProvider
		/// based on the specified id.
		/// </summary>
		protected override Page DataSelect(int id)
		{
			return BlogService.SelectPage(id);
		}

		/// <summary>
		/// Updates the object in its data store.
		/// </summary>
		protected override void DataUpdate()
		{
			BlogService.UpdatePage(this);
		}

		/// <summary>
		/// Inserts a new page to current BlogProvider.
		/// </summary>
		protected override void DataInsert()
		{
			BlogService.InsertPage(this);

			if (IsNew)
				Pages.Add(this);
		}

		/// <summary>
		/// Deletes the page from the current BlogProvider.
		/// </summary>
		protected override void DataDelete()
		{
			BlogService.DeletePage(this);
			if (Pages.Contains(this))
				Pages.Remove(this);
		}

		/// <summary>
		/// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
		/// </returns>
		public override string ToString()
		{
			return Title;
		}

		#endregion
	}
}